﻿using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.GeometryNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Bentley.CIMNET.CIMGeometry.Solid.SolidUtil.Modify;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;

namespace CheccFillTheChute.Tools
{
    class CreateCulvertAisle
    {
        //##########################涵洞通道-YBL################################

        public CulvertAisleElement culvertAisleElement;
        /// <summary>
        /// 创建通道
        /// </summary>
        /// <param name="culvertAisleParameter">参数</param>
        public CreateCulvertAisle(CulvertAisleParameter culvertAisleParameter)
        {
            culvertAisleParameter.culvertBottomSlope = culvertAisleParameter.culvertBottomSlope / 100;

            #region 创建搁置板、盖板、挡块
            double LateralOffset = Math.Abs((culvertAisleParameter.spanLength / 2) * Math.Tan((90 - culvertAisleParameter.angle_L) * Math.PI / 180));
            double LateralOffset_R = Math.Abs((culvertAisleParameter.spanLength / 2) * Math.Tan((90 - culvertAisleParameter.angle_R) * Math.PI / 180));
            culvertAisleParameter.length += LateralOffset + LateralOffset_R;
            SolidKernelEntity shelveSE_L = null;
            SolidKernelEntity cuboidSE_L = null;
            SolidKernelEntity stopDogSE_L = null;
            SolidKernelEntity shelveSE_R = null;
            SolidKernelEntity cuboidSE_R = null;
            SolidKernelEntity stopDogSE_R = null;
            if (culvertAisleParameter.isGutterway)
            {
                if (culvertAisleParameter.gutterwayLocation == "左侧" || culvertAisleParameter.gutterwayLocation == "两侧")
                {
                    //搁置板
                    shelveSE_L = CreateCuboid(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2), 0, 0), culvertAisleParameter.shelveWidth_L, culvertAisleParameter.stopDogHigh_L - culvertAisleParameter.CoverPlateThickness_L, culvertAisleParameter.length, culvertAisleParameter.culvertBottomSlope, culvertAisleParameter.dgnModel, culvertAisleParameter.chamferLength);

                    //盖板
                    cuboidSE_L = CreateCuboid(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2), 0, culvertAisleParameter.stopDogHigh_L - culvertAisleParameter.CoverPlateThickness_L), culvertAisleParameter.shelveWidth_L + culvertAisleParameter.gutterwayWidth_L + culvertAisleParameter.bracketWidth_L, culvertAisleParameter.CoverPlateThickness_L, culvertAisleParameter.length, culvertAisleParameter.culvertBottomSlope, culvertAisleParameter.dgnModel);

                    //挡块
                    stopDogSE_L = CreateStopDog(true, DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2) + culvertAisleParameter.shelveWidth_L + culvertAisleParameter.gutterwayWidth_L + culvertAisleParameter.stopDogThickness_L, 0, 0), culvertAisleParameter.stopDogSlope_L, culvertAisleParameter.bracketWidth_L, culvertAisleParameter.stopDogThickness_L, culvertAisleParameter.stopDogHigh_L, culvertAisleParameter.CoverPlateThickness_L, culvertAisleParameter.length, culvertAisleParameter.culvertBottomSlope, culvertAisleParameter.dgnModel);
                }

                if (culvertAisleParameter.gutterwayLocation == "右侧" || culvertAisleParameter.gutterwayLocation == "两侧")
                {
                    //搁置板
                    shelveSE_R = CreateCuboid(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2, 0, 0), culvertAisleParameter.shelveWidth_R, culvertAisleParameter.stopDogHigh_R - culvertAisleParameter.CoverPlateThickness_R, culvertAisleParameter.length, culvertAisleParameter.culvertBottomSlope, culvertAisleParameter.dgnModel, culvertAisleParameter.chamferLength);

                    //盖板
                    cuboidSE_R = CreateCuboid(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2, 0, culvertAisleParameter.stopDogHigh_R - culvertAisleParameter.CoverPlateThickness_R), culvertAisleParameter.shelveWidth_R + culvertAisleParameter.gutterwayWidth_R + culvertAisleParameter.bracketWidth_R, culvertAisleParameter.CoverPlateThickness_R, culvertAisleParameter.length, culvertAisleParameter.culvertBottomSlope, culvertAisleParameter.dgnModel);

                    //挡块
                    stopDogSE_R = CreateStopDog(false, DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2 - culvertAisleParameter.shelveWidth_R - culvertAisleParameter.gutterwayWidth_R - culvertAisleParameter.stopDogThickness_R, 0, 0), culvertAisleParameter.stopDogSlope_R, culvertAisleParameter.bracketWidth_R, culvertAisleParameter.stopDogThickness_R, culvertAisleParameter.stopDogHigh_R, culvertAisleParameter.CoverPlateThickness_R, culvertAisleParameter.length, culvertAisleParameter.culvertBottomSlope, culvertAisleParameter.dgnModel);
                }
            }
            #endregion

            #region 铺装
            List<SolidKernelEntity> matFoemationSEList = new List<SolidKernelEntity>();
            //铺装实时厚度 
            double matFormationSumThickness = 0;
            for (int i = culvertAisleParameter.matFormation_dgv.RowCount - 1; i >= 0; i--)
            {
                //铺装厚度
                double matFormationThickness = Convert.ToDouble(culvertAisleParameter.matFormation_dgv[1, i].Value) / 100;
                //铺装材料
                string matFormationMaterials = culvertAisleParameter.matFormation_dgv[2, i].Value.ToString();
                //路拱横坡
                double crossSlope = Convert.ToDouble(culvertAisleParameter.matFormation_dgv[3, i].Value);
                List<DPoint3d> matFormationPoint = new List<DPoint3d>();

                if ((culvertAisleParameter.gutterwayLocation == "左侧" || culvertAisleParameter.gutterwayLocation == "两侧") && matFormationSumThickness < culvertAisleParameter.stopDogHigh_L)
                {
                    matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2) + culvertAisleParameter.shelveWidth_L + culvertAisleParameter.gutterwayWidth_L + culvertAisleParameter.stopDogThickness_L, 0, matFormationSumThickness));

                    if (matFormationSumThickness + matFormationThickness > culvertAisleParameter.stopDogHigh_L)
                    {
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2) + culvertAisleParameter.shelveWidth_L + culvertAisleParameter.gutterwayWidth_L + culvertAisleParameter.stopDogThickness_L, 0, culvertAisleParameter.stopDogHigh_L));
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2), 0, culvertAisleParameter.stopDogHigh_L));
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2), 0, matFormationSumThickness + matFormationThickness));
                    }
                    else
                    {
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2) + culvertAisleParameter.shelveWidth_L + culvertAisleParameter.gutterwayWidth_L + culvertAisleParameter.stopDogThickness_L, 0, matFormationSumThickness + matFormationThickness));
                    }
                }
                else
                {
                    if(i==0&& culvertAisleParameter.chamferLength!= 0)
                    {
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2)+ culvertAisleParameter.chamferLength, 0, matFormationSumThickness));
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2), 0, matFormationSumThickness+ culvertAisleParameter.chamferLength));
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2), 0, matFormationSumThickness + matFormationThickness));
                    }
                    else
                    {
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2), 0, matFormationSumThickness));
                        matFormationPoint.Add(DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength / 2), 0, matFormationSumThickness + matFormationThickness));
                    }
                    
                }
                List<DPoint3d> point_R = new List<DPoint3d>();
                if ((culvertAisleParameter.gutterwayLocation == "右侧" || culvertAisleParameter.gutterwayLocation == "两侧") && matFormationSumThickness < culvertAisleParameter.stopDogHigh_R)
                {
                    point_R.Add(DPoint3d.FromXYZ((culvertAisleParameter.spanLength / 2) - culvertAisleParameter.shelveWidth_R - culvertAisleParameter.gutterwayWidth_R - culvertAisleParameter.stopDogThickness_R, 0, matFormationSumThickness));
                    if (matFormationSumThickness + matFormationThickness > culvertAisleParameter.stopDogHigh_L)
                    {
                        point_R.Add(DPoint3d.FromXYZ((culvertAisleParameter.spanLength / 2) - culvertAisleParameter.shelveWidth_L - culvertAisleParameter.gutterwayWidth_L - culvertAisleParameter.stopDogThickness_L, 0, culvertAisleParameter.stopDogHigh_L));
                        point_R.Add(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2, 0, culvertAisleParameter.stopDogHigh_L));
                        point_R.Add(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2, 0, matFormationSumThickness + matFormationThickness));
                    }
                    else
                    {
                        point_R.Add(DPoint3d.FromXYZ((culvertAisleParameter.spanLength / 2) - culvertAisleParameter.shelveWidth_R - culvertAisleParameter.gutterwayWidth_R - culvertAisleParameter.stopDogThickness_R, 0, matFormationSumThickness + matFormationThickness));
                    }
                }
                else
                {
                    if (i == 0 && culvertAisleParameter.chamferLength != 0)
                    {
                        point_R.Add(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2- culvertAisleParameter.chamferLength, 0, matFormationSumThickness));
                        point_R.Add(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2, 0, matFormationSumThickness + culvertAisleParameter.chamferLength));
                        point_R.Add(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2, 0, matFormationSumThickness + matFormationThickness));
                    }
                    else
                    {
                        point_R.Add(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2, 0, matFormationSumThickness));
                        point_R.Add(DPoint3d.FromXYZ(culvertAisleParameter.spanLength / 2, 0, matFormationSumThickness + matFormationThickness));
                    }

                }
                if (i == 0 && crossSlope != 0)
                {
                    DPoint3d crossSlope_L = matFormationPoint[matFormationPoint.Count - 1];
                    DPoint3d crossSlope_R = point_R[point_R.Count - 1];
                    double b = crossSlope_L.Z - crossSlope * crossSlope_L.X;
                    double y = crossSlope * ((crossSlope_L.X + crossSlope_R.X) / 2) + b;
                    DPoint3d crossSlopePOint = DPoint3d.FromXYZ((crossSlope_L.X + crossSlope_R.X) / 2, 0, y);
                    matFormationPoint.Add(crossSlopePOint);
                }
                point_R.Reverse();
                matFormationPoint.AddRange(point_R);
                for (int k = 0; k < matFormationPoint.Count; k++)
                {
                    matFormationPoint[k] = matFormationPoint[k] * UorPerMeter();
                }
                SolidKernelEntity matFoemationSE = CreatePointSmartSolid(matFormationPoint, culvertAisleParameter.length, culvertAisleParameter.culvertBottomSlope, culvertAisleParameter.dgnModel);
                matFormationSumThickness += matFormationThickness;
                matFoemationSEList.Add(matFoemationSE);
            }
            #endregion

            #region 创建剪切体
            culvertAisleParameter.length -= (LateralOffset + LateralOffset_R);

            List<List<DPoint3d>> lstSlab_Dpoint = new List<List<DPoint3d>>();
            if (culvertAisleParameter.angle_L < 90)
            {
                List<DPoint3d> clipDpointHead = new()
                {
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),LateralOffset,-100)*UorPerMeter(),
                 DPoint3d.FromXYZ(culvertAisleParameter.spanLength/2,-LateralOffset,-100)*UorPerMeter(),
                 DPoint3d.FromXYZ(culvertAisleParameter.spanLength/2,-LateralOffset,100)*UorPerMeter(),
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),LateralOffset,100)*UorPerMeter(),
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),LateralOffset,-100)*UorPerMeter(),
                };
                lstSlab_Dpoint.Add(clipDpointHead);
            }
            else
            {
                List<DPoint3d> clipDpointHead = new()
                {
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),-LateralOffset,-100)*UorPerMeter(),
                 DPoint3d.FromXYZ(culvertAisleParameter.spanLength/2,LateralOffset,-100)*UorPerMeter(),
                 DPoint3d.FromXYZ(culvertAisleParameter.spanLength/2,LateralOffset,100)*UorPerMeter(),
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),-LateralOffset,100)*UorPerMeter(),
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),-LateralOffset,-100)*UorPerMeter(),
                };
                lstSlab_Dpoint.Add(clipDpointHead);
            }

            if (culvertAisleParameter.angle_R < 90)
            {
                List<DPoint3d> clipDpointTrail = new()
                {
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),culvertAisleParameter.length+LateralOffset_R,-100)*UorPerMeter(),
                 DPoint3d.FromXYZ(culvertAisleParameter.spanLength/2,culvertAisleParameter.length-LateralOffset_R,-100)*UorPerMeter(),
                 DPoint3d.FromXYZ(culvertAisleParameter.spanLength/2,culvertAisleParameter.length-LateralOffset_R,100)*UorPerMeter(),
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),culvertAisleParameter.length+LateralOffset_R,100)*UorPerMeter(),
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),culvertAisleParameter.length+LateralOffset_R,-100)*UorPerMeter(),
                };
                lstSlab_Dpoint.Add(clipDpointTrail);
            }
            else
            {
                List<DPoint3d> clipDpointTrail = new()
                {
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),culvertAisleParameter.length-LateralOffset_R,-100)*UorPerMeter(),
                 DPoint3d.FromXYZ(culvertAisleParameter.spanLength/2,culvertAisleParameter.length+LateralOffset_R,-100)*UorPerMeter(),
                 DPoint3d.FromXYZ(culvertAisleParameter.spanLength/2,culvertAisleParameter.length+LateralOffset_R,100)*UorPerMeter(),
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),culvertAisleParameter.length-LateralOffset_R,100)*UorPerMeter(),
                 DPoint3d.FromXYZ(-(culvertAisleParameter.spanLength/2),culvertAisleParameter.length-LateralOffset_R,-100)*UorPerMeter(),
                };
                lstSlab_Dpoint.Add(clipDpointTrail);
            }

            #endregion

            #region 剪切通道体的头尾
            culvertAisleElement = new CulvertAisleElement();

            double z = culvertAisleParameter.culvertBottomSlope * -LateralOffset;

            DPoint3d movePoint3d = new DPoint3d(0, -LateralOffset, z) * UorPerMeter();
            DTransform3d transform3D = DTransform3d.Identity;
            transform3D.Translation = movePoint3d;
            if (shelveSE_L != null)
            {
                SolidKernelEntity[] lstSlab_Head = new SolidKernelEntity[2];
                lstSlab_Head[0] = CreatePointSmartSolid(lstSlab_Dpoint[0], culvertAisleParameter.length, -DVector3d.UnitY, culvertAisleParameter.dgnModel);
                lstSlab_Head[1] = CreatePointSmartSolid(lstSlab_Dpoint[1], culvertAisleParameter.length, DVector3d.UnitY, culvertAisleParameter.dgnModel);
                TransformBody(ref shelveSE_L, transform3D);
                BodyBooleanSubtract(ref shelveSE_L, ref lstSlab_Head, 2);
                Convert1.BodyToElement(out Element shelveOut, shelveSE_L, null, culvertAisleParameter.dgnModel);
                culvertAisleElement.shelveElement_L = shelveOut;
            }
            if (cuboidSE_L != null)
            {
                SolidKernelEntity[] lstSlab_Head = new SolidKernelEntity[2];
                lstSlab_Head[0] = CreatePointSmartSolid(lstSlab_Dpoint[0], culvertAisleParameter.length, -DVector3d.UnitY, culvertAisleParameter.dgnModel);
                lstSlab_Head[1] = CreatePointSmartSolid(lstSlab_Dpoint[1], culvertAisleParameter.length, DVector3d.UnitY, culvertAisleParameter.dgnModel);
                TransformBody(ref cuboidSE_L, transform3D);
                BodyBooleanSubtract(ref cuboidSE_L, ref lstSlab_Head, 2);
                Convert1.BodyToElement(out Element cuboidOut, cuboidSE_L, null, culvertAisleParameter.dgnModel);
                culvertAisleElement.cuboidElement_L = cuboidOut;
            }
            if (stopDogSE_L != null)
            {
                SolidKernelEntity[] lstSlab_Head = new SolidKernelEntity[2];
                lstSlab_Head[0] = CreatePointSmartSolid(lstSlab_Dpoint[0], culvertAisleParameter.length, -DVector3d.UnitY, culvertAisleParameter.dgnModel);
                lstSlab_Head[1] = CreatePointSmartSolid(lstSlab_Dpoint[1], culvertAisleParameter.length, DVector3d.UnitY, culvertAisleParameter.dgnModel);
                TransformBody(ref stopDogSE_L, transform3D);
                BodyBooleanSubtract(ref stopDogSE_L, ref lstSlab_Head, 2);
                Convert1.BodyToElement(out Element stopDogOut, stopDogSE_L, null, culvertAisleParameter.dgnModel);
                culvertAisleElement.stopDogElement_L = stopDogOut;
            }
            if (shelveSE_R != null)
            {
                SolidKernelEntity[] lstSlab_Head = new SolidKernelEntity[2];
                lstSlab_Head[0] = CreatePointSmartSolid(lstSlab_Dpoint[0], culvertAisleParameter.length, -DVector3d.UnitY, culvertAisleParameter.dgnModel);
                lstSlab_Head[1] = CreatePointSmartSolid(lstSlab_Dpoint[1], culvertAisleParameter.length, DVector3d.UnitY, culvertAisleParameter.dgnModel);
                TransformBody(ref shelveSE_R, transform3D);
                BodyBooleanSubtract(ref shelveSE_R, ref lstSlab_Head, 2);
                Convert1.BodyToElement(out Element shelveOut, shelveSE_R, null, culvertAisleParameter.dgnModel);
                culvertAisleElement.shelveElement_R = shelveOut;
            }
            if (cuboidSE_R != null)
            {
                SolidKernelEntity[] lstSlab_Head = new SolidKernelEntity[2];
                lstSlab_Head[0] = CreatePointSmartSolid(lstSlab_Dpoint[0], culvertAisleParameter.length, -DVector3d.UnitY, culvertAisleParameter.dgnModel);
                lstSlab_Head[1] = CreatePointSmartSolid(lstSlab_Dpoint[1], culvertAisleParameter.length, DVector3d.UnitY, culvertAisleParameter.dgnModel);
                TransformBody(ref cuboidSE_R, transform3D);
                BodyBooleanSubtract(ref cuboidSE_R, ref lstSlab_Head, 2);
                Convert1.BodyToElement(out Element cuboidOut, cuboidSE_R, null, culvertAisleParameter.dgnModel);
                culvertAisleElement.cuboidElement_R = cuboidOut;
            }
            if (stopDogSE_R != null)
            {
                SolidKernelEntity[] lstSlab_Head = new SolidKernelEntity[2];
                lstSlab_Head[0] = CreatePointSmartSolid(lstSlab_Dpoint[0], culvertAisleParameter.length, -DVector3d.UnitY, culvertAisleParameter.dgnModel);
                lstSlab_Head[1] = CreatePointSmartSolid(lstSlab_Dpoint[1], culvertAisleParameter.length, DVector3d.UnitY, culvertAisleParameter.dgnModel);
                TransformBody(ref stopDogSE_R, transform3D);
                BodyBooleanSubtract(ref stopDogSE_R, ref lstSlab_Head, 2);
                Convert1.BodyToElement(out Element stopDogOut, stopDogSE_R, null, culvertAisleParameter.dgnModel);
                culvertAisleElement.stopDogElement_R = stopDogOut;
            }
            foreach (SolidKernelEntity item in matFoemationSEList)
            {
                if (item == null)
                    continue;
                SolidKernelEntity[] lstSlab_Head = new SolidKernelEntity[2];
                lstSlab_Head[0] = CreatePointSmartSolid(lstSlab_Dpoint[0], culvertAisleParameter.length, -DVector3d.UnitY, culvertAisleParameter.dgnModel);
                lstSlab_Head[1] = CreatePointSmartSolid(lstSlab_Dpoint[1], culvertAisleParameter.length, DVector3d.UnitY, culvertAisleParameter.dgnModel);
                SolidKernelEntity solidKernelEntity = item as SolidKernelEntity;
                TransformBody(ref solidKernelEntity, transform3D);
                BodyBooleanSubtract(ref solidKernelEntity, ref lstSlab_Head, 2);
                Convert1.BodyToElement(out Element seOut, solidKernelEntity, null, culvertAisleParameter.dgnModel);
                culvertAisleElement.matFoemationElement.Add(seOut);
            }
            #endregion
        }

        /// <summary>
        /// 创建长方体
        /// </summary>
        /// <param name="location">基准点(针对左边为左下)</param>
        /// <param name="width">搁置板宽度</param>
        /// <param name="high">搁置板高度</param>
        /// <param name="length">体长</param>
        /// <param name="dgnModel">放置视图</param>
        /// <returns></returns>
        private SolidKernelEntity CreateCuboid(DPoint3d location, double width, double high, double length, double culvertSlope, DgnModel dgnModel, double chamferLength = 0)
        {
            DPoint3d dPoint3D = DPoint3d.FromXYZ(0, 0, location.Z);
            if (chamferLength == 0)
            {
                List<DPoint3d> points = new()
                {
                  location * UorPerMeter(),
                  GetNformMNAndLL(location,dPoint3D,width)* UorPerMeter(),
                  DPoint3d.FromXYZ(GetNformMNAndLL(location,dPoint3D,width).X,GetNformMNAndLL(location,dPoint3D,width).Y,GetNformMNAndLL(location,dPoint3D,width).Z+high)* UorPerMeter(),
                  DPoint3d.FromXYZ(location.X,location.Y,location.Z+high)* UorPerMeter(),
                  location* UorPerMeter()
                };
                return CreatePointSmartSolid(points, length, culvertSlope, dgnModel);
            }
            else
            {
                List<DPoint3d> points = new()
                {
                  DPoint3d.FromXYZ(location.X,location.Y,location.Z+chamferLength)* UorPerMeter(),
                  GetNformMNAndLL(location,dPoint3D,chamferLength)* UorPerMeter(),
                  GetNformMNAndLL(location,dPoint3D,width)* UorPerMeter(),
                  DPoint3d.FromXYZ(GetNformMNAndLL(location,dPoint3D,width).X,GetNformMNAndLL(location,dPoint3D,width).Y,GetNformMNAndLL(location,dPoint3D,width).Z+high)* UorPerMeter(),
                  DPoint3d.FromXYZ(location.X,location.Y,location.Z+high)* UorPerMeter(),
                  DPoint3d.FromXYZ(location.X,location.Y,location.Z+chamferLength)* UorPerMeter()
                };
                return CreatePointSmartSolid(points, length, culvertSlope, dgnModel);
            }
        }

        /// <summary>
        /// 创建挡块
        /// </summary>
        /// <param name="isLeft">是否为左边</param>
        /// <param name="location">基准点（针对左边为右下）</param>
        /// <param name="slope">挡块坡度</param>
        /// <param name="bracketWidth">牛腿宽</param>
        /// <param name="stopDogThickness">挡块厚</param>
        /// <param name="stopDogHigh">挡块高</param>
        /// <param name="CoverPlateThickness">盖板厚</param>
        /// <param name="length">体长</param>
        /// <param name="dgnModel">放置视图</param>
        /// <returns></returns>
        private SolidKernelEntity CreateStopDog(bool isLeft, DPoint3d location, double slope, double bracketWidth, double stopDogThickness, double stopDogHigh, double CoverPlateThickness, double length, double culvertSlope, DgnModel dgnModel)
        {
            List<DPoint3d> stopDogPoint = new();

            double slopeWidth = (stopDogHigh - CoverPlateThickness) * slope;
            if (isLeft)
            {
                List<DPoint3d> points = new List<DPoint3d>()
                {
                    location* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X,location.Y,location.Z+stopDogHigh)* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X-(stopDogThickness-bracketWidth),location.Y,location.Z+stopDogHigh)* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X-(stopDogThickness-bracketWidth),location.Y,location.Z+stopDogHigh-CoverPlateThickness)* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X-stopDogThickness,location.Y,location.Z+stopDogHigh-CoverPlateThickness)* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X-stopDogThickness-slopeWidth,location.Y,location.Z)* UorPerMeter(),
                    location* UorPerMeter()
                };
                stopDogPoint = points;
            }
            else
            {
                List<DPoint3d> points = new List<DPoint3d>()
                {
                    location* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X,location.Y,location.Z+stopDogHigh)* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X+(stopDogThickness-bracketWidth),location.Y,location.Z+stopDogHigh)* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X+(stopDogThickness-bracketWidth),location.Y,location.Z+stopDogHigh-CoverPlateThickness)* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X+stopDogThickness,location.Y,location.Z+stopDogHigh-CoverPlateThickness)* UorPerMeter(),
                    DPoint3d.FromXYZ(location.X+stopDogThickness+slopeWidth,location.Y,location.Z)* UorPerMeter(),
                    location* UorPerMeter()
                };
                stopDogPoint = points;
            }
            return CreatePointSmartSolid(stopDogPoint, length, culvertSlope, dgnModel);
        }

        /// <summary>
        /// 创建实体 点集有分辨率
        /// </summary>
        /// <param name="points"></param>
        /// <param name="Width"></param>
        public static SolidKernelEntity CreatePointSmartSolid(List<DPoint3d> points, double Width, double slope, DgnModel dgnModel)
        {
            double b = points[0].Z / UorPerMeter() - slope * points[0].Y / UorPerMeter();
            double z = slope * (points[0].Y / UorPerMeter() + Width) + b;

            ShapeElement sectiongElement = new ShapeElement(dgnModel, null, points.ToArray());
            CurveVector secCur = CurvePathQuery.ElementToCurveVector(sectiongElement);
            LineElement lineElement = new LineElement(dgnModel, null, new DSegment3d(points[0], DPoint3d.FromXYZ(points[0].X / UorPerMeter(), points[0].Y / UorPerMeter() + Width, z) * UorPerMeter()));
            CurveVector pathCur = CurvePathQuery.ElementToCurveVector(lineElement);
            BCIMNETGS.SolidUtil.Create.BodyFromSweep(out SolidKernelEntity entity, secCur, pathCur, dgnModel, false, true, false, null, null, null, null);
            //SolidKernelEntity solidKernel = CreateBodyFromExtrusion(secCur, Width, DVector3d.UnitY, dgnModel);
            return entity;
        }
        /// <summary>
        /// 创建实体 点集有分辨率
        /// </summary>
        /// <param name="points"></param>
        /// <param name="Width"></param>
        public static SolidKernelEntity CreatePointSmartSolid(List<DPoint3d> points, double Width, DVector3d dVector3D, DgnModel dgnModel)
        {
            ShapeElement sectiongElement = new ShapeElement(dgnModel, null, points.ToArray());
            CurveVector secCur = CurvePathQuery.ElementToCurveVector(sectiongElement);
            SolidKernelEntity solidKernel = CreateBodyFromExtrusion(secCur, Width, dVector3D, dgnModel);
            return solidKernel;
        }

        public static SolidKernelEntity CreateBodyFromExtrusion(CurveVector secCur, double extrusionLength, DVector3d extrudDir, DgnModel modelRef)
        {
            //TransformSectionNormaltoSolidPath(ref secCur, centroid, extrudDir);
            BentleyStatus status = Bentley.CIMNET.CIMGeometry.Solid.SolidUtil.Create.BodyFromExtrusion(
                out SolidKernelEntity entity, secCur, extrusionLength * modelRef.GetModelInfo().UorPerMaster, modelRef, extrudDir, false, null);
            return entity;
        }

        /// <summary>
        /// 计算延长点
        /// </summary>
        /// <param name="M">原点</param>
        /// <param name="N">指向点</param>
        /// <param name="LL">指定延长的长度</param>
        /// <returns></returns>
        private DPoint3d GetNformMNAndLL(DPoint3d M, DPoint3d N, double LL)
        {
            DPoint3d PT = new DPoint3d();

            DVector3d VM = new DVector3d(M);
            DVector3d VN = new DVector3d(N);

            DVector3d MN = new DVector3d();

            MN = DVector3d.Subtract(VN, VM);

            double len = VM.Distance(VN);
            double Bei = (LL / len);

            MN.ScaleInPlace(Bei);
            VN = DVector3d.Add(MN, VM);
            PT = new DPoint3d(VN);

            return PT;
        }

        public static double UorPerMeter()
        {
            ModelInfo modelInfo = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel().GetModelInfo();
            double uorsPerMeter = modelInfo.UorPerMeter;
            return uorsPerMeter;
        }
    }

    public class CulvertAisleElement
    {
        public Element shelveElement_L;
        public Element cuboidElement_L;
        public Element stopDogElement_L;
        public Element shelveElement_R;
        public Element cuboidElement_R;
        public Element stopDogElement_R;
        public List<Element> matFoemationElement = new();
    }

    public class CulvertAisleParameter
    {
        //跨径
        public double spanLength;
        //左角度
        public double angle_L;
        //右角度
        public double angle_R;
        //涵底坡度
        public double culvertBottomSlope;
        //视图
        public DgnModel dgnModel;
        //涵洞长
        public double length;
        //倒角
        public double chamferLength;
        //铺装
        public DataGridView matFormation_dgv;
        //是否设置排水沟
        public bool isGutterway;
        //排水沟位置
        public string gutterwayLocation;
        //两侧尺寸
        public string twoFlanksSize;
        //挡块材料
        public string stopDogMaterials;
        //盖板材料
        public string coverPlateMaterials;
        //搁置板材料
        public string shelveMaterials;

        //左侧挡块高度
        public double stopDogHigh_L;
        //左侧挡块厚度
        public double stopDogThickness_L;
        //左侧牛腿宽
        public double bracketWidth_L;
        //左侧排水沟宽
        public double gutterwayWidth_L;
        //左侧盖板厚度
        public double CoverPlateThickness_L;
        //左侧搁置板宽
        public double shelveWidth_L;
        //左侧挡块坡度
        public double stopDogSlope_L;

        //右侧挡块高度
        public double stopDogHigh_R;
        //右侧挡块厚度
        public double stopDogThickness_R;
        //右侧牛腿宽
        public double bracketWidth_R;
        //右侧排水沟宽
        public double gutterwayWidth_R;
        //右侧盖板厚度
        public double CoverPlateThickness_R;
        //右侧搁置板宽
        public double shelveWidth_R;
        //右侧挡块坡度
        public double stopDogSlope_R;


    }
}
